<script setup>
import { ref } from 'vue';
import { useToast } from 'primevue/usetoast';
import axios from 'axios';

const toast = useToast();

// 数据状态
const totalSize = ref(0); // 总文件大小
const totalSizePercent = ref(0); // 上传进度百分比
const files = ref([]); // 选择的文件列表
const uploadedFiles = ref([]); // 已上传的文件列表

// 移除文件
const onRemoveTemplatingFile = (file, removeFileCallback, index) => {
    removeFileCallback(index);
    totalSize.value -= parseInt(formatSize(file.size));
    totalSizePercent.value = totalSize.value / 10;
};

// 清空文件
const onClearTemplatingUpload = (clear) => {
    clear();
    totalSize.value = 0;
    totalSizePercent.value = 0;
    files.value = [];
};

// 选择文件
const onSelectedFiles = (event) => {
    files.value = event.files;
    files.value.forEach((file) => {
        totalSize.value += parseInt(formatSize(file.size));
    });
};

// 自定义上传方法
const customUpload = async () => {
    if (files.value.length === 0) {
        toast.add({ severity: 'warn', summary: '警告', detail: '请先选择文件', life: 3000 });
        return;
    }

    const formData = new FormData();
    files.value.forEach((file) => {
        formData.append('files[]', file);
    });

    try {
        const response = await axios.post('/api/upload', formData, {
            headers: {
                'Content-Type': 'multipart/form-data'
            },
            onUploadProgress: (progressEvent) => {
                // 计算上传进度
                totalSizePercent.value = Math.round((progressEvent.loaded * 100) / progressEvent.total);
            }
        });

        // 上传成功处理
        uploadedFiles.value = [...uploadedFiles.value, ...files.value];
        toast.add({ severity: 'success', summary: '成功', detail: '文件上传成功', life: 3000 });
        files.value = []; // 清空待上传文件
        totalSize.value = 0; // 重置总大小
        totalSizePercent.value = 0; // 重置进度条
    } catch (error) {
        // 上传失败处理
        toast.add({ severity: 'error', summary: '错误', detail: '文件上传失败', life: 3000 });
        console.error('上传失败:', error);
    }
};

// 格式化文件大小
const formatSize = (bytes) => {
    const k = 1024;
    const dm = 3;
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];

    if (bytes === 0) {
        return `0 ${sizes[0]}`;
    }

    const i = Math.floor(Math.log(bytes) / Math.log(k));
    const formattedSize = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));

    return `${formattedSize} ${sizes[i]}`;
};
</script>

<template>
    <div class="card">
        <Toast />
        <FileUpload name="demo[]" :multiple="true" accept="image/*" :maxFileSize="1000000" :auto="false" :customUpload="true" @select="onSelectedFiles">
            <template #header="{ chooseCallback, clearCallback }">
                <div class="flex flex-wrap justify-between items-center flex-1 gap-4">
                    <div class="flex gap-2">
                        <Button @click="chooseCallback()" icon="pi pi-images" rounded outlined severity="secondary"></Button>
                        <Button @click="customUpload" icon="pi pi-cloud-upload" rounded outlined severity="success" :disabled="files.length === 0"></Button>
                        <Button @click="onClearTemplatingUpload(clearCallback)" icon="pi pi-times" rounded outlined severity="danger" :disabled="files.length === 0"></Button>
                    </div>
                    <ProgressBar :value="totalSizePercent" :showValue="false" class="md:w-20rem h-1 w-full md:ml-auto">
                        <span class="whitespace-nowrap">{{ totalSize }}B / 1Mb</span>
                    </ProgressBar>
                </div>
            </template>
            <template #content="{ files, removeFileCallback }">
                <div class="flex flex-col gap-8 pt-4">
                    <div v-if="files.length > 0">
                        <h5>待上传文件</h5>
                        <div class="flex flex-wrap gap-4">
                            <div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
                                <div>
                                    <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
                                </div>
                                <span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
                                <div>{{ formatSize(file.size) }}</div>
                                <Badge value="待上传" severity="warn" />
                                <Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, removeFileCallback, index)" outlined rounded severity="danger" />
                            </div>
                        </div>
                    </div>

                    <div v-if="uploadedFiles.length > 0">
                        <h5>已上传文件</h5>
                        <div class="flex flex-wrap gap-4">
                            <div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
                                <div>
                                    <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
                                </div>
                                <span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
                                <div>{{ formatSize(file.size) }}</div>
                                <Badge value="已上传" class="mt-4" severity="success" />
                            </div>
                        </div>
                    </div>
                </div>
            </template>
            <template #empty>
                <div class="flex items-center justify-center flex-col">
                    <i class="pi pi-cloud-upload !border-2 !rounded-full !p-8 !text-4xl !text-muted-color" />
                    <p class="mt-6 mb-0">拖放文件到这里上传</p>
                </div>
            </template>
        </FileUpload>
    </div>
</template>
